package com.jim.healio.graphrag.service;

import com.jim.healio.graphrag.model.MedicalDocument;
import com.jim.healio.graphrag.model.DocumentSearchResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 简化的文档服务
 * 临时替代复杂的向量存储实现
 */
@Service
public class SimplifiedDocumentService {
    
    private static final Logger logger = LoggerFactory.getLogger(SimplifiedDocumentService.class);
    
    // 内存存储，生产环境中应该使用真正的向量数据库
    private final Map<String, MedicalDocument> documentStore = new ConcurrentHashMap<>();
    
    /**
     * 存储医学文档
     */
    public void storeDocument(MedicalDocument document) {
        logger.info("存储文档: {}", document.getTitle());
        documentStore.put(document.getId(), document);
    }
    
    /**
     * 批量存储文档
     */
    public void storeDocuments(List<MedicalDocument> documents) {
        logger.info("批量存储 {} 个文档", documents.size());
        for (MedicalDocument doc : documents) {
            storeDocument(doc);
        }
    }
    
    /**
     * 语义搜索文档（简化实现）
     */
    public List<DocumentSearchResult> semanticSearch(String query, int limit) {
        logger.info("执行语义搜索: {}, 限制: {}", query, limit);
        
        List<DocumentSearchResult> results = new ArrayList<>();
        
        for (MedicalDocument doc : documentStore.values()) {
            double similarity = calculateSimilarity(query, doc);
            
            if (similarity > 0.3) { // 相似度阈值
                DocumentSearchResult result = new DocumentSearchResult();
                result.setDocumentId(doc.getId());
                result.setTitle(doc.getTitle());
                result.setContent(doc.getContent());
                result.setSimilarity(similarity);
                result.setSource(doc.getSource());
                
                // 设置元数据
                Map<String, Object> metadata = Map.of(
                    "id", doc.getId(),
                    "title", doc.getTitle(),
                    "type", doc.getType().name(),
                    "source", doc.getSource() != null ? doc.getSource() : "",
                    "author", doc.getAuthor() != null ? doc.getAuthor() : "",
                    "tags", String.join(",", doc.getTags()),
                    "entities", String.join(",", doc.getExtractedEntityIds())
                );
                result.setMetadata(metadata);
                
                // 设置高亮文本
                String content = doc.getContent();
                if (content.length() > 200) {
                    result.setHighlightedText(content.substring(0, 200) + "...");
                } else {
                    result.setHighlightedText(content);
                }
                
                results.add(result);
            }
        }
        
        // 按相似度排序并限制结果数量
        results.sort((a, b) -> Double.compare(b.getSimilarity(), a.getSimilarity()));
        
        List<DocumentSearchResult> limitedResults = results.stream()
            .limit(limit)
            .collect(Collectors.toList());
        
        logger.info("语义搜索完成，找到 {} 个结果", limitedResults.size());
        return limitedResults;
    }
    
    /**
     * 根据实体ID查询相关文档
     */
    public List<DocumentSearchResult> queryDocumentsByEntity(String entityId, int limit) {
        logger.info("根据实体查询文档: {}, 限制: {}", entityId, limit);
        
        List<DocumentSearchResult> results = new ArrayList<>();
        
        for (MedicalDocument doc : documentStore.values()) {
            if (doc.getExtractedEntityIds().contains(entityId)) {
                DocumentSearchResult result = convertToSearchResult(doc);
                result.setSimilarity(0.9); // 实体匹配给高相似度
                result.addMatchedEntity(entityId);
                results.add(result);
            }
        }
        
        // 按相似度排序并限制结果数量
        results.sort((a, b) -> Double.compare(b.getSimilarity(), a.getSimilarity()));
        
        List<DocumentSearchResult> limitedResults = results.stream()
            .limit(limit)
            .collect(Collectors.toList());
        
        logger.info("实体文档查询完成，找到 {} 个结果", limitedResults.size());
        return limitedResults;
    }
    
    /**
     * 混合搜索：结合语义搜索和实体过滤
     */
    public List<DocumentSearchResult> hybridSearch(String query, List<String> entityIds, int limit) {
        logger.info("执行混合搜索: {}, 实体: {}, 限制: {}", query, entityIds, limit);
        
        // 先进行语义搜索
        List<DocumentSearchResult> semanticResults = semanticSearch(query, limit * 2);
        
        if (entityIds == null || entityIds.isEmpty()) {
            return semanticResults.subList(0, Math.min(semanticResults.size(), limit));
        }
        
        // 过滤包含指定实体的文档
        List<DocumentSearchResult> filteredResults = semanticResults.stream()
            .filter(result -> {
                String entities = (String) result.getMetadata().get("entities");
                if (entities == null) return false;
                return entityIds.stream().anyMatch(entities::contains);
            })
            .limit(limit)
            .collect(Collectors.toList());
        
        logger.info("混合搜索完成，找到 {} 个结果", filteredResults.size());
        return filteredResults;
    }
    
    /**
     * 删除文档
     */
    public void deleteDocument(String documentId) {
        logger.info("删除文档: {}", documentId);
        documentStore.remove(documentId);
    }
    
    /**
     * 获取所有文档
     */
    public List<MedicalDocument> getAllDocuments() {
        return new ArrayList<>(documentStore.values());
    }
    
    /**
     * 获取文档数量
     */
    public int getDocumentCount() {
        return documentStore.size();
    }
    
    /**
     * 检查服务是否可用
     */
    public boolean isAvailable() {
        return true; // 简化实现总是可用
    }
    
    /**
     * 计算查询和文档的相似度（简化实现）
     */
    private double calculateSimilarity(String query, MedicalDocument document) {
        String docText = (document.getTitle() + " " + document.getContent()).toLowerCase();
        String queryLower = query.toLowerCase();
        
        // 简单的关键词匹配算法
        String[] queryWords = queryLower.split("\\s+");
        int matches = 0;
        
        for (String word : queryWords) {
            if (docText.contains(word)) {
                matches++;
            }
        }
        
        // 计算匹配比例
        double similarity = (double) matches / queryWords.length;
        
        // 标题匹配加权
        if (document.getTitle().toLowerCase().contains(queryLower)) {
            similarity += 0.3;
        }
        
        // 标签匹配加权
        for (String tag : document.getTags()) {
            if (tag.toLowerCase().contains(queryLower)) {
                similarity += 0.2;
                break;
            }
        }
        
        return Math.min(similarity, 1.0); // 最大相似度为1.0
    }
    
    /**
     * 将MedicalDocument转换为DocumentSearchResult
     */
    private DocumentSearchResult convertToSearchResult(MedicalDocument document) {
        DocumentSearchResult result = new DocumentSearchResult();
        result.setDocumentId(document.getId());
        result.setTitle(document.getTitle());
        result.setContent(document.getContent());
        result.setSource(document.getSource());
        
        // 设置元数据
        Map<String, Object> metadata = Map.of(
            "id", document.getId(),
            "title", document.getTitle(),
            "type", document.getType().name(),
            "source", document.getSource() != null ? document.getSource() : "",
            "entities", String.join(",", document.getExtractedEntityIds())
        );
        result.setMetadata(metadata);
        
        // 设置高亮文本
        String content = document.getContent();
        if (content.length() > 200) {
            result.setHighlightedText(content.substring(0, 200) + "...");
        } else {
            result.setHighlightedText(content);
        }
        
        return result;
    }
} 